home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 24
/
Amiga Format AFCD24 (Feb 1998, Issue 108).iso
/
-in_the_mag-
/
emulation
/
amiga
/
uae-0.7.0b2
/
src
/
od-amiga
/
ami-disk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-20
|
13KB
|
472 lines
/*
* UAE - The Un*x Amiga Emulator
*
* ami-disk.c: Creates pseudo dev: handler. Copy tracks to rawfile
* (used in zfile.c).
*
* 08/06/97: Modified to avoid a spilled registers error message
* when used with the new fd2inline convention.
*
* Copyright 1996 Samuel Devulder.
*/
/****************************************************************************/
#include <exec/execbase.h>
#include <exec/memory.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <dos/dos.h>
#include <devices/trackdisk.h>
/* This should cure the spilled-register problem. An other solution is to */
/* compile with -O2 instead of -O3 */
#define NO_INLINE_STDARGS
#define __NOINLINES__
#include <proto/exec.h>
#ifndef __SASC
#include <proto/alib.h>
#endif
#include <proto/dos.h>
/****************************************************************************/
#include "sysconfig.h"
#include "sysdeps.h"
#include <ctype.h>
#include <signal.h>
#include "config.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "keyboard.h"
#include "keybuf.h"
#include "disk.h"
#include "debug.h"
#include "gui.h"
/****************************************************************************/
char *amiga_dev_path = "DEV:";
char *ixemul_dev_path = "/dev/";
int readdevice(char *name, char *dst);
void initpseudodevices(void);
void closepseudodevices(void);
char *to_unix_path(char *s);
char *from_unix_path(char *s);
void split_dir_file(char *src, char **dir, char **file);
static void myDoIO(struct IOStdReq *ioreq, LONG CMD, LONG FLAGS, LONG OFFSET,
LONG LENGTH, LONG DATA);
/****************************************************************************/
static char *pseudo_dev_path = "T:DEV";
static char pseudo_dev_created = 0;
static char pseudo_dev_assigned = 0;
static char dfx_done[4];
static int device_exists(char *device_name, int device_unit);
static int dev_inhibit(char *dev,int on);
static void set_req(int ok);
/****************************************************************************/
/* support routines to handle unix filename convention
*/
char *to_unix_path(char *s)
{
char *t,*r,*u;
int l;
#ifndef __GNUC
return my_strdup(s);
#endif
for(u=s,l=0;*u;++u,++l) if(*u=='/' || *u==':') l+=2;
r = t = malloc(1+l);
if(!r) return NULL;
for(u=s;*u && *u!=':';++u);
if(*u) {
*t++='/';
while(*s!=':') *t++=*s++;
*t++='/';++s;
}
while(*s=='/') {*t++='.';*t++='.';*t++=*s++;}
while(*s) {
if(s[0]=='/' && s[1]=='/') {*t++=*s++;*t++='.';*t++='.';*t++=*s++;}
else *t++=*s++;
}
*t='\0';
return r;
}
/****************************************************************************/
char *from_unix_path(char *s)
{
char *t,*r;
r = t = malloc(strlen(s)+1);
if(!r) return NULL;
#ifndef __GNUC__
strcpy(r,s);
return r;
#endif
if(*s=='/') {
++s;
while(*s && *s!='/') *t++=*s++;
if(*s=='/') {*t++=':';++s;}
}
while(*s) {
if(s[0]=='.' && s[1]=='.') s+=2;
else *t++=*s++;
}
*t='\0';
return r;
}
/****************************************************************************/
void split_dir_file(char *src, char **dir, char **file)
{ /* note: src is freed() */
char *s=src;
while(*s) ++s;
while(s>src && (*s!=':' && *s!='/')) --s;
if(*s==':' || *s=='/') {
*file = my_strdup(s+1);
s[1] = '\0';
*dir = my_strdup(src);
free(src);
} else {
*file = src;
*dir = my_strdup("");
}
}
/****************************************************************************/
/*
* Creates peudo DEV:DFx files.
*/
void initpseudodevices(void)
{
ULONG lock;
int i;
pseudo_dev_created = 0;
pseudo_dev_assigned = 0;
for(i=0;i<4;++i) dfx_done[i]=0;
/* check if dev: already exists */
set_req(0);lock = Lock(amiga_dev_path,SHARED_LOCK);set_req(1);
if(!lock) {
char name[80];
set_req(0);lock = Lock(pseudo_dev_path,SHARED_LOCK);set_req(1);
if(!lock) {
/* create it */
lock = CreateDir(pseudo_dev_path);
if(!lock) goto fail;
UnLock(lock);lock = Lock(pseudo_dev_path,SHARED_LOCK);
pseudo_dev_created = 1;
}
strcpy(name,amiga_dev_path);
if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
if(!AssignLock(name,lock)) {UnLock(lock);goto fail;}
/* the lock is the assign now */
pseudo_dev_assigned = 1;
} else UnLock(lock);
/* Create the dev:DFi entry */
for(i=0;i<4;++i) if(device_exists("trackdisk.device",i)) {
ULONG fd;
char name[80];
sprintf(name,"%sDF%d",amiga_dev_path,i);
fd = Open(name,MODE_NEWFILE);
if(fd) {Close(fd);dfx_done[i]=1;}
}
return;
fail:
fprintf(stderr,"Failed to create pseudo dev: entry!\n");
}
/****************************************************************************/
/*
* Cleanup pseudo DEV:DFx
*/
void closepseudodevices(void)
{
int i;
for(i=0;i<4;++i) if(dfx_done[i]) {
char name[80];
sprintf(name,"%sDF%d",amiga_dev_path,i);
DeleteFile(name);
dfx_done[i] = 0;
}
if(pseudo_dev_assigned) {
char name[80];
strcpy(name,amiga_dev_path);
if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
AssignLock(name,NULL);
pseudo_dev_assigned = 0;
}
if(pseudo_dev_created) {
DeleteFile(pseudo_dev_path);
pseudo_dev_created = 0;
}
}
/****************************************************************************/
/*
* Enable/Disable system requester
*/
static void set_req(int ok)
{
static ULONG wd = 0;
struct Process *pr;
pr = (void*)FindTask(NULL);
if(pr->pr_Task.tc_Node.ln_Type != NT_PROCESS) return;
if(ok) {
pr->pr_WindowPtr = (APTR)wd;
}
else {
wd = (ULONG)pr->pr_WindowPtr;
pr->pr_WindowPtr = (APTR)-1;
}
}
/****************************************************************************/
/*
* checks if a device exists
*/
static int device_exists(char *device_name, int device_unit)
{
struct IOStdReq *ioreq = NULL;
struct MsgPort *port = NULL;
int ret = 0;
port = CreatePort(0, 0);
if(port) {
ioreq = CreateStdIO(port);
if(ioreq) {
if(!OpenDevice(device_name,device_unit,(void*)ioreq,0)) {
CloseDevice((void*)ioreq);
ret = 1;
}
DeleteStdIO(ioreq);
}
DeletePort(port);
}
return ret;
}
/****************************************************************************/
/*
* extract the device and unit form a filename.
*/
static void extract_dev_unit(char *name, char **dev_name, int *dev_unit)
{
char *s;
if(tolower(name[0])=='d' && tolower(name[1])=='f' &&
name[2]>='0' && name[2]<='3' && name[3]=='\0') {
/* DF0 */
*dev_unit = name[2]-'0';
*dev_name = strdup("trackdisk.device");
} else if((s = strrchr(name,'/'))) {
/* trackdisk[.device]/0 */
*dev_unit = atoi(s+1);
*dev_name = malloc(1 + s-name);
if(*dev_name) {
strncpy(*dev_name, name, 1 + s-name);
(*dev_name)[s-name]='\0';
}
} else {
/* ?? STRANGEDISK0: ?? */
*dev_unit = 0;
*dev_name = strdup(name);
}
if(*dev_name) {
char *s;
if(!(s = strrchr(*dev_name,'.'))) {
/* .device is missing */
s = malloc(8+strlen(*dev_name));
if(s) {
sprintf(s,"%s.device",*dev_name);
free(*dev_name);
*dev_name = s;
}
}
}
}
/****************************************************************************/
/*
* copy a device to a FILE*.
*/
static int raw_copy(char *dev_name, int dev_unit, FILE *dst)
{
struct MsgPort *port = NULL;
struct IOStdReq *ioreq = NULL;
int tracklen = 512*11;
int retstatus = 1;
int inhibited = 0;
char *buffer = NULL;
static char name[] = {'D','F','0','\0'};
if(!strcmp(dev_name, "trackdisk.device")) {
inhibited = 1;
name[2] = '0'+dev_unit;
}
/* allocate system stuff */
if((port = CreatePort(0, 0))) {
if((ioreq = CreateStdIO(port))) {
if((buffer = AllocMem(tracklen, MEMF_CHIP))) {
/* gain access to the device */
if(!OpenDevice(dev_name, dev_unit, (struct IORequest*)ioreq, 0)) {
/* check if a disk is present */
myDoIO(ioreq, TD_CHANGESTATE, 0, -1, -1, -1);
if(!ioreq->io_Error && ioreq->io_Actual) {
fprintf(stderr,"No disk in %s unit %d !\n", dev_name, dev_unit);
retstatus = 0;
} else {
int tr = 0;
int write_protected = 0;
/* check if disk is write-protected:
myDoIO(ioreq, TD_PROTSTATUS, 0, -1, -1, -1);
if(!ioreq->io_Error && ioreq->io_Actual) write_protected = 1;
*/
/* inhibit device */
if(inhibited) inhibited = dev_inhibit(name,1);
/* read tracks */
for(tr = 0; tr < 160; ++tr) {
printf("Reading track %2d side %d of %s unit %d \r",
tr/2, tr%2, dev_name, dev_unit);
fflush(stdout);
myDoIO(ioreq, CMD_READ, -1, tracklen*tr, tracklen, (LONG)buffer);
if(ioreq->io_Error) printf("Err. on\n");
if(fwrite(buffer, 1, tracklen, dst) != (unsigned int)tracklen) {
retstatus = 0;
break;
}
}
/* ok everything done! */
printf(" \r");
fflush(stdout);
/* stop motor */
myDoIO(ioreq, TD_MOTOR, 0, -1, 0, -1);
/* uninhibit */
if(inhibited) dev_inhibit(name,0);
}
CloseDevice((struct IORequest*)ioreq); } else retstatus = 0;
FreeMem(buffer,tracklen); } else retstatus = 0;
DeleteStdIO(ioreq); } else retstatus = 0;
DeletePort(port); } else retstatus = 0;
return retstatus;
}
/****************************************************************************/
/*
* Copy one raw disk to a file.
*/
int readdevice(char *name, char *dst)
{ /* erhm, I must admit this code is long and ugly! */
FILE *f = NULL;
char *device_name;
int device_unit;
int retstatus = 0;
#ifdef HAVE_SIGACTION
struct sigaction oldsa;
int oldsa_valid;
/* disable break */
oldsa_valid = (0==sigaction(SIGINT, NULL, &oldsa));
signal(SIGINT, SIG_IGN); /* <--- gcc complains about something */
/* in there but I don't know why. */
#endif
/* get device name & unit */
extract_dev_unit(name, &device_name, &device_unit);
if(device_name) {
/* if no destination then just check if the device exists */
if(dst == NULL)
retstatus = device_exists(device_name, device_unit);
else {
/* open dest file */
if((f = fopen(dst,"wb"))) {
retstatus = raw_copy(device_name, device_unit, f);
fclose(f);
}
}
free(device_name);
}
#ifdef HAVE_SIGACTION
/* enable break */
if(oldsa_valid) sigaction(SIGINT, &oldsa, NULL);
#endif
return retstatus;
}
/****************************************************************************/
static void myDoIO(struct IOStdReq *ioreq, LONG CMD, LONG FLAGS, LONG OFFSET,
LONG LENGTH, LONG DATA)
{
if(CMD>=0) ioreq->io_Command = CMD;
if(FLAGS>=0) ioreq->io_Flags = FLAGS;
if(OFFSET>=0) ioreq->io_Offset = OFFSET;
if(LENGTH>=0) ioreq->io_Length = LENGTH;
if(DATA>=0) ioreq->io_Data = (void*)DATA;
DoIO((struct IORequest*)ioreq);
}
/****************************************************************************/
/*
* Prevents DOS to access a DFx device.
*/
static int dev_inhibit(char *dev,int on)
{
char buff[10],*s;
struct MsgPort *DevPort;
if(!*dev) return 0;
s=dev;while(*s++);
if(s[-2]==':') strcpy(buff,dev); else sprintf(buff,"%s:",dev);
if((DevPort = (struct MsgPort*)DeviceProc((STRPTR)buff))) {
if(on) {
DoPkt(DevPort,ACTION_INHIBIT,DOSTRUE,NULL,NULL,NULL,NULL);
return 1;
}
else DoPkt(DevPort,ACTION_INHIBIT,DOSFALSE,NULL,NULL,NULL,NULL);
}
return 0;
}